# -*- coding: utf-8 -*-
"""Controlador de Analizadores Lexicos"""
from formencode import validators
from lex import model
from lex.lib.base import BaseController
from lex.model import metadata, DBSession
from lex.model.model import AnalizadorLexico, Alfabeto
from lex.widgets import analizadores_form
from lex.widgets.analizadores_form import crear_analizador_form, \
    editar_analizador_form
from pylons.i18n import ugettext as _, lazy_ugettext as l_
from sqlalchemy import func
from sqlalchemy.exc import IntegrityError, SQLAlchemyError
from tg import expose, flash, require, url, request, redirect, tmpl_context, \
    validate
import transaction
from webhelpers import paginate

from repoze.what import predicates
from tgext.admin.controller import AdminController, AdminConfig
from tgext.admin.tgadminconfig import TGAdminConfig


__all__ = ['AnalizadoresController']

class AnalizadoresController(BaseController):

    @expose('lex.templates.analizadores.listado_analizadores')    
    def listado_analizadores(self, **kw):
        return dict()
    
    @validate(validators={"page":validators.Int(), "rp":validators.Int()})
    @expose('json')
    def datos(self, page='1', rp='25', sortname='nombre', sortorder='asc', qtype=None, query=None):
        """Metodo para listar todos los Analizadores existentes en la base de datos"""
        try:
            # Obtenemos todos los objetos "AnalizadorLexico".
            analizadores = DBSession.query(AnalizadorLexico).order_by(AnalizadorLexico.id_analizador_lexico)
            total = analizadores.count()
            rows = [{'id'  : analizador.id_analizador_lexico,
                        'cell': [analizador.id_analizador_lexico,
                analizador.nombre_analizador_lexico,
                            analizador.estado]} for analizador in analizadores]
            result = dict(page=page, total=total, rows=rows)
        except:
                result = dict() 
        return result
     

    @expose('lex.templates.analizadores.nuevo_analizador')
    def nuevo_analizador(self, **kw):
        """Despliega el formulario para añadir un nuevo Analizador Lexico"""
        try:
            # Establecemos el contexto de nuestro formulario de creacion de analizador lexico.
            tmpl_context.form = crear_analizador_form
        except SQLAlchemyError:
            flash(_("No se pudo acceder a Creacion de Analizadores! SQLAlchemyError..."), 'error')
            redirect("/analizadores/listado_analizadores")
        except (AttributeError, NameError):
            flash(_("No se pudo acceder a Creacion de Analizador! Hay Problemas con el servidor..."), 'error')
            redirect("/analizadores/listado_analizadores")

        return dict(nombre_modelo='Analizador Lexico', value=kw)

    @validate(crear_analizador_form, error_handler=nuevo_analizador)
    @expose()
    def add(self, **kw):
        """Metodo para agregar un registro a la base de datos """
        try:
            # Realizamos algunas comprobaciones del nombre del analizador.
            nombre_analizador = kw['nombre_analizador_lexico']
            lista_nombre = nombre_analizador.split()
            nombre_analizador = " ".join(lista_nombre)

            # Creamos un nuevo analizador lexico e insertamos en la BD.
            analizador = AnalizadorLexico()
            analizador.nombre_analizador_lexico = nombre_analizador
            analizador.estado = False
            DBSession.add(analizador)

            
            

            # Confirmamos la transaccion.
            DBSession.flush()
            transaction.commit()
        except IntegrityError:
            transaction.abort()
            flash(_("No se ha guardado! Hay Problemas con el servidor..."), 'error')
            redirect("/analizadores/listado_analizadores")
        except SQLAlchemyError:
            flash(_("No se ha guardado! SQLAlchemyError..."), 'error')
            redirect("/analizadores/listado_analizadores")
        except (AttributeError, NameError):
            flash(_("No se ha guardado! Hay Problemas con el servidor..."), 'error')
            redirect("/analizadores/listado_analizadores")
        else:
            flash(_("Analizador creado!"), 'ok')
    
        redirect("/analizadores/listado_analizadores")

    @expose('lex.templates.analizadores.editar_analizador')
    def editar_analizador(self, id_analizador_lexico, **kw):
        """Metodo que rellena el formulario para editar un Analizador Lexico"""
        try:
            # Establecemos el contexto del formulario de edicion de analizadores lexicos.
            tmpl_context.form = editar_analizador_form

            # Cargamos el formulario con los datos del analizador lexico a editar.
            analizador = DBSession.query(AnalizadorLexico).get(id_analizador_lexico)
            kw['id_analizador_lexico'] = analizador.id_analizador_lexico
            kw['nombre_analizador_lexico'] = analizador.nombre_analizador_lexico
            kw['estado'] = analizador.estado
        except SQLAlchemyError:
            flash(_("No se pudo acceder a Edicion de Analizadores! SQLAlchemyError..."), 'error')
            redirect("/analizadores/listado_analizadores")
        except (AttributeError, NameError):
            flash(_("No se pudo acceder a Edicion de Analizadores! Hay Problemas con el servidor..."), 'error')
            redirect("/analizadores/listado_analizadores")

        return dict(value=analizador)

    @validate(editar_analizador_form, error_handler=editar_analizador)
    @expose()
    def update(self, **kw):        
        """Metodo que actualizar la base de datos"""
        try:
            # Realizamos algunas comprobaciones del nombre del analizador.
            nombre_analizador = kw['nombre_analizador_lexico']
            lista_nombre = nombre_analizador.split()
            nombre_analizador = " ".join(lista_nombre)

            # Guardamos los cambios realizados en la edicion del analizador lexico.
            analizador = DBSession.query(AnalizadorLexico).get(kw['id_analizador_lexico'])
            analizador.nombre_analizador_lexico = nombre_analizador
            analizador.estado = kw['estado']

            # Confirmamos la transaccion
            DBSession.flush()
            transaction.commit()
        except IntegrityError:
            transaction.abort()
            flash(_("No se han guardado los cambios! Hay Problemas con el servidor..."), 'error')
            redirect("/analizadores/listado_analizadores")
        except SQLAlchemyError:
            flash(_("No se han guardado los cambios! SQLAlchemyError..."), 'error')
            redirect("/analizadores/listado_analizadores")
        except (AttributeError, NameError):
            flash(_("No se han guardado los cambios! Hay Problemas con el servidor..."), 'error')
            redirect("/analizadores/listado_analizadores")
        else:
            flash(_("Se han guardado los cambios!"), 'ok')

        redirect("/analizadores/listado_analizadores")

    @expose('lex.templates.analizadores.confirmar_eliminar_analizador')
    def confirmar_eliminar_analizador(self, id_analizador_lexico, **kw):
        """Despliega confirmacion de eliminacion"""
        try:
            # Se muestran los datos del analizador lexico seleccionado.
            analizador = DBSession.query(AnalizadorLexico).get(id_analizador_lexico)
        except SQLAlchemyError:
            flash(_("No se pudo acceder a Eliminacion de Analizadores! SQLAlchemyError..."), 'error')
            redirect("/analizadores/listado_analizadores")
        except (AttributeError, NameError):
            flash(_("No se pudo acceder a Eliminacion de Analizadores! Hay Problemas con el servidor..."), 'error')
            redirect("/analizadores/listado_analizadores")

        return dict(value=analizador)

    @expose()
    def delete(self, id_analizador_lexico, **kw):
        """Metodo que elimina un registro de la base de datos"""
        try:
            # Al eliminar un analizador se debe eliminar recursivamente todos sus datos adjuntos.
##########################################################



##########################################################
            analizador_a_eliminar = DBSession.query(AnalizadorLexico).get(id_analizador_lexico)
            nombre = analizador_a_eliminar.nombre_analizador_lexico
            print("sadkjf;kljdf;kajsdl;fkjasf", nombre)
            DBSession.delete(DBSession.query(AnalizadorLexico).get(id_analizador_lexico))
            DBSession.flush()
            transaction.commit()
        except IntegrityError:
            transaction.abort()
            msg = "No se ha eliminado! Hay Problemas con el servidor..."
            type = "error"
            redirect("/analizadores/datos")
        except SQLAlchemyError:
            msg = "No se ha eliminado! Hay Problemas con el servidor..."
            type = "error"
            redirect("/analizadores/datos")
        except (AttributeError, NameError):
            msg = "No se ha eliminado! Hay Problemas con el servidor..."
            type = "error"
            redirect("/analizadores/datos")
        else:
            msg = "El analizador se ha eliminado con exito!."
            type = "succes"

        return dict(msg=msg, nombre=nombre, type=type)

    @expose("lex.templates.analizadores.listar_alfabetos")
    def listar_alfabetos(self, id_analizador_lexico, page=1):
        """Metodo para listar todos los alfabetos que tiene el analizador seleccionado"""
        try:
            #Se obtienen todos los alfabetos que forman parte del analizador lexico.
            analizador = DBSession.query(AnalizadorLexico).get(id_analizador_lexico)
            alfabetos = analizador.alfabetos
            currentPage = paginate.Page(alfabetos, page, items_per_page=10)
        except SQLAlchemyError:
            flash(_("No se pudo acceder a Alfabetos del Analizador Lexico! SQLAlchemyError..."), 'error')
            redirect("/analizadores/listado_analizadores")
        except (AttributeError, NameError):
            flash(_("No se pudo acceder a Alfabetos del Analizador Lexico! Hay Problemas con el servidor..."), 'error')
            redirect("/analizadores/listado_analizadores")

        return dict(alfabetos=currentPage.items, currentPage=currentPage, analizador=analizador)

    @expose()
    def eliminar_analizador_alfabeto(self, id_analizador_lexico, id_alfabeto, **kw):
        """Metodo que elimina un alfabeto del analizador seleccionado"""
        try:
            #Se desasigna un alfabeto que formaba parte del analizador lexico.
            analizador = DBSession.query(AnalizadorLexico).get(id_analizador_lexico)
            alfabeto = DBSession.query(Alfabeto).get(id_alfabeto)
            
            if analizador.alfabetos.count(alfabeto) >= 1: 
               analizador.alfabetos.remove(alfabeto)

            DBSession.flush()
            transaction.commit()
        except IntegrityError:
            transaction.abort()
            flash(_("No se pudo desasignar el Alfabeto! Hay Problemas con el servidor..."), 'error')
            redirect("/analizadores/listar_alfabetos", id_analizador_lexico=id_analizador_lexico)
        except SQLAlchemyError:
            flash(_("No se pudo desasignar el Alfabeto! SQLAlchemyError..."), 'error')
            redirect("/analizadores/listar_alfabetos", id_analizador_lexico=id_analizador_lexico)
        except (AttributeError, NameError):
            flash(_("No se pudo desasignar el Alfabeto! Hay Problemas con el servidor..."), 'error')
            redirect("/analizadores/listar_alfabetos", id_analizador_lexico=id_analizador_lexico)
        except (ValueError):
            redirect("/analizadores/listar_alfabetos", id_analizador_lexico=id_analizador_lexico)
        else:
            flash(_("Alfabeto desasignado!"), 'ok')

        redirect("/analizadores/listar_alfabetos", id_analizador_lexico=id_analizador_lexico)

    @expose("lex.templates.analizadores.agregar_alfabetos")
    def agregar_alfabetos(self, id_analizador_lexico, page=1):
        """Metodo que permite listar los alfabetos que se pueden agregar al analizador seleccionado"""
        try:
            #Se obtienen todos los alfabetos que pueden formar parte del analizador lexico.
            analizador = DBSession.query(AnalizadorLexico).get(id_analizador_lexico)
            alfabetos_del_analizador = analizador.alfabetos
            alfabetos = DBSession.query(Alfabeto).all()
        
            for alfabeto_del_analizador in alfabetos_del_analizador:
                if alfabetos.count(alfabeto_del_analizador) >= 1: 
                   alfabetos.remove(alfabeto_del_analizador)

            currentPage = paginate.Page(alfabetos, page, items_per_page=10)
        except SQLAlchemyError:
            flash(_("No se pudo acceder a Asignar Alfabetos! SQLAlchemyError..."), 'error')
            redirect("/analizadores/listar_alfabetos", id_analizador_lexico=id_analizador_lexico)
        except (AttributeError, NameError):
            flash(_("No se pudo acceder a Asignar Alfabetos! Hay Problemas con el servidor..."), 'error')
            redirect("/analizadores/listar_alfabetos", id_analizador_lexico=id_analizador_lexico)

        return dict(alfabetos=currentPage.items, currentPage=currentPage, analizador=analizador)

    @expose()
    def agregar_alfabeto(self, id_analizador_lexico, id_alfabeto):
        """Metodo que realiza la agregacion de un alfabeto al analizador selecccionado"""
        try:
            #Se asigna un alfabeto que no formaba parte del analizador lexico.
            analizador = DBSession.query(AnalizadorLexico).get(id_analizador_lexico)
            alfabeto = DBSession.query(Alfabeto).get(id_alfabeto)
            analizador.alfabetos.append(alfabeto)
            DBSession.flush()
            transaction.commit()
        except IntegrityError:            
            redirect("/analizadores/analizador_alfabeto",id_analizador_lexico=id_analizador_lexico)
        except SQLAlchemyError:
            flash(_("No se pudo asignar el Permiso! SQLAlchemyError..."), 'error')
            redirect("/analizadores/agregar_alfabetos",id_analizador_lexico=id_analizador_lexico)
        except (AttributeError, NameError):
            flash(_("No se pudo asignar el Permiso! Hay Problemas con el servidor..."), 'error')
            redirect("/analizadores/agregar_alfabetos",id_analizador_lexico=id_analizador_lexico)
        else:
            flash(_("Alfabeto asignado!"), 'ok')

        redirect("/analizadores/agregar_alfabetos",id_analizador_lexico=id_analizador_lexico)